package com.hzw.saas.service.msg.listener;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import javax.annotation.Resource;

import com.hzw.saas.api.group.IGroupMemberService;
import com.hzw.saas.api.group.IGroupService;
import com.hzw.saas.api.group.event.MemberLeaveGroupEvent;
import com.hzw.saas.api.msg.IMsgOperationService;
import com.hzw.saas.api.msg.IMsgService;
import com.hzw.saas.api.msg.enums.MsgType;
import com.hzw.saas.api.msg.event.SendMsgEvent;
import com.hzw.saas.api.user.IUserAccountService;
import com.hzw.saas.common.config.util.AssertUtil;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 * 通用的事件监听入口
 * </p>
 *
 * @author sonam
 * @since 2021/3/18 16:29
 */
@Slf4j
@Order(1)
@Component
@RequiredArgsConstructor
public class CommonListener {

    @Resource(name = "msgServiceImpl")
    private IMsgService msgService;
    @Resource(name = "msgOperationServiceImpl")
    private IMsgOperationService msgOperationService;
    @Resource(name = "groupServiceImpl")
    private IGroupService groupService;
    @Resource(name = "userAccountServiceImpl")
    private IUserAccountService userAccountService;
    @Resource(name = "groupMemberServiceImpl")
    private IGroupMemberService groupMemberService;

    /**
     * 当前成员离开群组时调用该方法
     */
    @Transactional
    @EventListener(MemberLeaveGroupEvent.class)
    public void memberLeaveGroupEvent(MemberLeaveGroupEvent event) {
        // 获取当前用户在该群组下所有的消息ID
        String userId = event.getUserId();
        String groupId = event.getGroupId();
        // 获取指定群组下当前用户下所有的消息ID
        List<String> groupMsgIds = msgService.getGroupMsgIds(Arrays.asList(groupId), userId, null);
        // 删除
        msgService.deleteMsgByMsgIdsAndUserId(groupMsgIds, userId);
        msgOperationService.deleteMsgOperatorByMsgIds(groupMsgIds);
    }

    /**
     * 当发送消息时，调用该方法
     */
    @EventListener(SendMsgEvent.class)
    public void sendMsgEvent(SendMsgEvent sendMsgEvent) {
        String to = sendMsgEvent.getTo();
        String from = sendMsgEvent.getFrom();
        MsgType msgType = sendMsgEvent.getMsgType();
        switch (msgType) {
            case SYSTEM_MSG:
                // 群发消息
                if (!Objects.equals("-1", to)) {
                    // 系统向指定用户发
                    AssertUtil.assertThrow("发送消息失败，发送的目标用户不存在",
                        !userAccountService.existAccount(to));
                }
                break;
            case USER_MSG:
                // 向某个用户发送系统消息
                AssertUtil.assertThrow("发送消息失败，不能向自己发送消息", Objects.equals(to, from));
                AssertUtil.assertThrow("发送消息失败，发送的目标用户不存在",
                    !userAccountService.existAccount(to));
                break;
            case GROUP_MSG:
                // 验证from是否有效
                AssertUtil.assertThrow("发送消息失败，指定的from必须存在的群组id", !groupService.doesExist(from));
                // 验证 to 是否有效
                // to 与 from 不相同时，有2种情况， 1、to=otherGroupId 2、to=userId
                if (!Objects.equals(from, to) && !groupService.doesExist(to)) {
                    AssertUtil.assertThrow("发送消息失败，发送的目标用户不在该群组里面", !groupMemberService.tryJoinGroup(to, from));
                }
                break;
            default:
                AssertUtil.assertThrow("发送消息失败，发送的消息类型无效", true);
        }
    }

}
